package tripleo.curr;

import java.util.ArrayList;
import java.util.List;

class Messages {
	static private long alloced=0;
	static long alloc() {return ++alloced;}
}

public class Timeout implements Runnable, Process {
	static Timeout instance = new Timeout();
	private It first = null;
	ProcessQ queue = ProcessQ.defaultInstance();
	private static final long WAKE = Messages.alloc();

	public void run() {
		if (its.size() > 1) {
			first = its.get(0);
			its.remove(0);
		}
		while (true) {
			if (first == null) {
				thread_sleep(500);
			} else {
				final long P = first.pros+first.inc;
				//
				System.out.println("NOW: "+curTime());
				System.out.println("UNTIL: "+P);
				//
				thread_sleep(P /*- curTime()*/);
				System.out.println("AT: "+curTime());
				//
				while (curTime() >= first.pros) {
					queue.send(this, first.cont, WAKE, first.value);
					if (its.size() > 0) {
						first = its.get(0);
						its.remove(0);
					} else first = null;
				}
			}
		}
	}

	void thread_sleep(final long aMillis) {
		try {
			Thread.sleep(aMillis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private long curTime() {
		return System.currentTimeMillis();
	}

	public void rcv(Process sender, long aMessage, Object aValue) {
		switch((int) aMessage ){

		}
	}

	Object lk=new Object();
	public Object rcvLock() {
		return lk;
	}

	class It {
		long inc, pros;
		Process cont;
		Object value;
	}

	List<It> its = new ArrayList();

	public void add(long ainc, Process aproc, Object avalue) {
		It it = new It();
		it.inc = ainc;
		it.pros = ainc + curTime();
		it.cont = aproc;
		it.value = avalue;
		its.add(it);
		if (its.size() < 1) first=it;
	}

	public void start() {
		new Thread(this, "Timeout").start();
	}
}

class  ProcessQ {
	private static ProcessQ instance;

	MessageResult send(Process from, Process to, long aMessage, Object aValue) {
		/**
		 * The us of rcvLock() is not acceptable for use here. A data
		 * structure which supports the wake up of an unspecified thread 
		 * when the tuple [from, message, value, continuation] is made
		 * available to it.  Unless in the case of sendFuture, the calling
		 * process is terminated until the continuation is invoked, and all
		 * bookeeping is finished.
		 */
		synchronized (to.rcvLock()) {
			try {
				to.rcv(from, aMessage, aValue);
				return MessageResult.Success();
			} catch (Exception e) {
				return MessageResult.Failure(e);
			}
		}
	}

	public static ProcessQ defaultInstance() {
		if (instance == null) {
			instance = new ProcessQ();
		}
		return instance;
	}
}
final class MessageResult {

	private Exception e;


	public static MessageResult Success() {
		return new MessageResult();
	}

	public static MessageResult Failure(Exception aE) {
		MessageResult m = new MessageResult();	
		m.e = aE;
		return m;
	}
	
	boolean isSuccess() {return e!=null;}
	
	
}
